package com.zb.frame.base.utils.encrypt;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.io.ByteArrayOutputStream;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

/**
 * <p>
 *  DES对称加密 工具类
 * </p>
 *
 * @author bangZZ
 * @since 2020-06-04
 */
public class DESUtil {

    private static Logger logger = LoggerFactory.getLogger(DESUtil.class);

    private final static String encoding = "UTF-8";

    static byte[] keyData = { 1, 9, 9, 6, 0, 7, 0, 7 };

    static DESUtil util = null;

    public static DESUtil getInstance(){
        if(null == util){
            util = new DESUtil();
        }
        return util;
    }

    SecretKey createDESSecretKey() throws NoSuchAlgorithmException, InvalidKeyException, InvalidKeySpecException {
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        return keyFactory.generateSecret(new DESKeySpec(keyData));
    }

    /**
     * 加密方法
     * @param str
     * @return
     */
    public String encrypt(String str) {
        BASE64Encoder base64encoder = new BASE64Encoder();
        String result = str;
        if (str != null && str.length() > 0) {
            try {
                byte[] encodeByte = symmetricEncrypto(str.getBytes(encoding));
                result = base64encoder.encode(encodeByte);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 解密方法
     * @param str
     * @return
     */
    public String decrypt(String str) {
        BASE64Decoder base64decoder = new BASE64Decoder();
        String result = trim(str);
        if (str != null && str.length() > 0) {
            try {
                byte[] encodeByte = base64decoder.decodeBuffer(str);
                byte[] decoder = symmetricDecrypto(encodeByte);
                result = new String(decoder, encoding);
            } catch (Exception e) {
                logger.warn("decrypt="+str+" "+e.getMessage());
            }
        }
        return result;
    }

    /**
     * 对称加密方法
     * @param byteSource 需要加密的数据
     * @return 经过加密的数据
     * @throws Exception
     */
    public byte[] symmetricEncrypto(byte[] byteSource) throws Exception {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            int mode = Cipher.ENCRYPT_MODE;
            Key key = createDESSecretKey();
            Cipher cipher = Cipher.getInstance("DES");
            cipher.init(mode, key);
            byte[] result = cipher.doFinal(byteSource);
            return result;
        } catch (Exception e) {
            throw e;
        } finally {
            baos.close();
        }
    }

    /**
     * 对称解密方法
     * @param byteSource 需要解密的数据
     * @return 经过解密的数据
     * @throws Exception
     */
    public byte[] symmetricDecrypto(byte[] byteSource) throws Exception {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try {
            int mode = Cipher.DECRYPT_MODE;
            Key key = createDESSecretKey();
            Cipher cipher = Cipher.getInstance("DES");
            cipher.init(mode, key);
            byte[] result = cipher.doFinal(byteSource);
            return result;
        } catch (Exception e) {
            throw e;
        } finally {
            byteArrayOutputStream.close();
        }
    }

    public static String trim(String str) {
        return str == null ? null : str.trim();
    }

    public static void main(String[] args) {
        String secret = getInstance().encrypt("root");
        System.out.println("加密后：" + secret);
        System.out.println("解密后：" + getInstance().decrypt(secret));

        /*String descode = PropertyUtil.getProperty("encrpty.keycode.des");
        System.out.println(descode);
        byte[] keyData = descode.getBytes();
        System.out.println(keyData);*/
    }
}
